package logic

import (
	"api/internal/svc"
	"api/internal/types"
	"api/service"
	"api/service/cert"
	"context"
	"github.com/go-pay/gopay"
	"github.com/go-pay/gopay/alipay"
	"github.com/zeromicro/go-zero/core/stores/sqlx"
	"strconv"

	"github.com/zeromicro/go-zero/core/logx"
)

type AliCreateOrderLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewAliCreateOrderLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AliCreateOrderLogic {
	return &AliCreateOrderLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

// 支付宝h5下单
func (l *AliCreateOrderLogic) AliCreateOrder(req *types.RequestCreateOrder) (resp *types.ResponseAliOrder, err error) {
	innerTradeNo := service.GenerateUniqueID(32) // 单号

	client, err := alipay.NewClient(cert.AliAPPID, cert.AliPrivateKey, true)
	if err != nil {
		l.Error("支付宝客户端实例失败", err)
		resp.Code = 500
		return resp, nil
	}
	client.AutoVerifySign(cert.AliPublicRSA2) // 自动验签 待测
	// 模式1:代开发根据商户code获取特约服务商auth TD
	// 模式2(商户自研)
	err = client.SetCertSnByContent(cert.AliAppCer, cert.AliRootCer, cert.AliPublicCer)
	if err != nil {
		l.Error("支付宝自动验签失败", err)
		resp.Code = 500
		return resp, nil
	}
	//配置公共参数
	client.SetCharset("utf-8").
		SetSignType(alipay.RSA2).
		SetNotifyUrl(cert.AliPayNotify)

	//请求参数
	description := "用户到店付款"
	bm := make(gopay.BodyMap)
	bm.Set("subject", description)
	bm.Set("out_trade_no", innerTradeNo)
	bm.Set("total_amount", req.Amount)
	bm.Set("buyer_open_id", req.OpenId)

	//小程序支付
	ret, err := client.TradeCreate(l.ctx, bm)
	if err != nil {
		l.Error("支付宝请求jsapi支付失败,内部单号:"+innerTradeNo, err)
		resp.Code = 500
		return resp, nil
	}

	// 创建单号
	conn := sqlx.NewMysql(l.svcCtx.Config.DataSource)
	orderService := service.NewOrderService(l.ctx, l.svcCtx)

	num, err := strconv.ParseFloat(req.Amount, 64) // 订单金额单位为分 前端传来是角
	num = num * 100

	discountNum, err := strconv.ParseFloat(req.Discount, 64) // 订单金额单位为分 前端传来是角
	discountNum = discountNum * 100

	err = orderService.CreateOrder(conn, int(num), req.Code, innerTradeNo, ret.Response.TradeNo, service.TYPE_ALI, req.CreateType, req.DiscountId, req.OpenId, int(discountNum), req.Table)
	if err != nil {
		return &types.ResponseAliOrder{
			Code:    0,
			TradeNo: "",
		}, nil
	}

	resp.TradeNo = ret.Response.TradeNo
	resp.Code = 200
	return resp, nil
}
